<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>数据可视化仪表盘</title>
  <script src="https://unpkg.com/vue@3"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
  <script src="https://unpkg.com/element-plus"></script>
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: Arial, sans-serif;
    }
    #app {
      display: flex;
      flex-direction: column;
      height: 100vh;
    }
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 20px;
      height: 60px;
      background-color: #409EFF;
      color: white;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
    }
    .main-content {
      flex: 1;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      gap: 10px;
      padding: 10px;
      overflow: auto;
    }
    .chart-container {
      background-color: #fff;
      border-radius: 4px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      padding: 10px;
      position: relative;
    }
    .chart-loading {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(255, 255, 255, 0.7);
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 10;
    }
    .footer {
      height: 50px;
      background-color: #409EFF;
      color: white;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    @media (max-width: 768px) {
      .main-content {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    @media (max-width: 480px) {
      .main-content {
        grid-template-columns: 1fr;
      }
    }
  </style>
</head>
<body>
  <div id="app">
    <!-- 顶部导航 -->
    <div class="header">
      <div class="header-left">
        <h2>数据可视化仪表盘</h2>
      </div>
      <div class="header-right">
        <el-dropdown>
          <span class="el-dropdown-link">
            菜单 <i class="el-icon-arrow-down el-icon--right"></i>
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item @click="refreshCharts">刷新数据</el-dropdown-item>
              <el-dropdown-item>设置</el-dropdown-item>
              <el-dropdown-item divided>退出登录</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>

    <!-- 主内容区 - 9宫格图表 -->
    <div class="main-content">
      <!-- 线图 -->
      <div class="chart-container" ref="chart1">
        <div v-if="loading.chart1" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 柱状图 -->
      <div class="chart-container" ref="chart2">
        <div v-if="loading.chart2" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 饼图 -->
      <div class="chart-container" ref="chart3">
        <div v-if="loading.chart3" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 散点图 -->
      <div class="chart-container" ref="chart4">
        <div v-if="loading.chart4" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 雷达图 -->
      <div class="chart-container" ref="chart5">
        <div v-if="loading.chart5" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 仪表盘 -->
      <div class="chart-container" ref="chart6">
        <div v-if="loading.chart6" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 漏斗图 -->
      <div class="chart-container" ref="chart7">
        <div v-if="loading.chart7" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 热力图 -->
      <div class="chart-container" ref="chart8">
        <div v-if="loading.chart8" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>

      <!-- 主题河流图 -->
      <div class="chart-container" ref="chart9">
        <div v-if="loading.chart9" class="chart-loading">
          <el-spinner type="el-icon-loading"></el-spinner>
        </div>
      </div>
    </div>

    <!-- 底部版权信息 -->
    <div class="footer">
      <span>© 2023 数据可视化仪表盘. 保留所有权利.</span>
    </div>
  </div>

  <script>
    const App = {
      data() {
        return {
          charts: [],
          loading: {
            chart1: true,
            chart2: true,
            chart3: true,
            chart4: true,
            chart5: true,
            chart6: true,
            chart7: true,
            chart8: true,
            chart9: true
          },
          error: {}
        };
      },
      mounted() {
        this.fetchAllChartData();
      },
      methods: {
        // 统一获取所有图表数据
        async fetchAllChartData() {
          // 修改为本地Flask服务器地址
          const apiBase = 'http://localhost:5000/api/charts';

          try {
            // 并行请求所有图表数据
            const [
              lineChartData,
              barChartData,
              pieChartData,
              scatterChartData,
              radarChartData,
              gaugeChartData,
              funnelChartData,
              heatmapChartData,
              themeRiverChartData
            ] = await Promise.all([
              this.fetchChartData(`${apiBase}/line`),
              this.fetchChartData(`${apiBase}/bar`),
              this.fetchChartData(`${apiBase}/pie`),
              this.fetchChartData(`${apiBase}/scatter`),
              this.fetchChartData(`${apiBase}/radar`),
              this.fetchChartData(`${apiBase}/gauge`),
              this.fetchChartData(`${apiBase}/funnel`),
              this.fetchChartData(`${apiBase}/heatmap`),
              this.fetchChartData(`${apiBase}/theme-river`)
            ]);

            // 初始化所有图表
            this.initChart1(lineChartData);
            this.initChart2(barChartData);
            this.initChart3(pieChartData);
            this.initChart4(scatterChartData);
            this.initChart5(radarChartData);
            this.initChart6(gaugeChartData);
            this.initChart7(funnelChartData);
            this.initChart8(heatmapChartData);
            this.initChart9(themeRiverChartData);

          } catch (error) {
            console.error('获取图表数据失败:', error);
            // 显示错误信息
            Object.keys(this.loading).forEach(key => {
              this.error[key] = '加载数据失败，请刷新重试';
            });
          }
        },

        // 通用数据获取方法
        async fetchChartData(url) {
          try {
            const response = await axios.get(url);
            return response.data;
          } catch (error) {
            console.error(`获取图表数据失败 (${url}):`, error);
            throw error;
          }
        },

        // 初始化线图
        initChart1(data) {
          const chart = echarts.init(this.$refs.chart1);
          chart.setOption({
            title: { text: '线图' },
            tooltip: {},
            xAxis: {
              type: 'category',
              data: data.xAxis || []
            },
            yAxis: {},
            series: [{
              name: data.seriesName || '数据',
              type: 'line',
              data: data.seriesData || [],
              smooth: true
            }]
          });
          this.charts.push(chart);
          this.loading.chart1 = false;

          // 窗口大小变化时重绘图表
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化柱状图
        initChart2(data) {
          const chart = echarts.init(this.$refs.chart2);
          chart.setOption({
            title: { text: '柱状图' },
            tooltip: {},
            xAxis: {
              type: 'category',
              data: data.xAxis || []
            },
            yAxis: {},
            series: [{
              name: data.seriesName || '数据',
              type: 'bar',
              data: data.seriesData || [],
              itemStyle: {
                color: '#409EFF'
              }
            }]
          });
          this.charts.push(chart);
          this.loading.chart2 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化饼图
        initChart3(data) {
          const chart = echarts.init(this.$refs.chart3);
          chart.setOption({
            title: { text: '饼图' },
            tooltip: {
              trigger: 'item',
              formatter: '{a} <br/>{b}: {c} ({d}%)'
            },
            legend: {
              type: 'scroll',
              orient: 'vertical',
              right: 10,
              top: 20,
              bottom: 20,
              data: data.legendData || []
            },
            series: [{
              name: data.seriesName || '数据',
              type: 'pie',
              radius: ['40%', '70%'],
              avoidLabelOverlap: false,
              label: {
                show: true,
                formatter: '{b}: {d}%'
              },
              data: data.seriesData || []
            }]
          });
          this.charts.push(chart);
          this.loading.chart3 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化散点图
        initChart4(data) {
          const chart = echarts.init(this.$refs.chart4);
          chart.setOption({
            title: { text: '散点图' },
            tooltip: {},
            xAxis: {},
            yAxis: {},
            series: [{
              symbolSize: 20,
              data: data.seriesData || [],
              type: 'scatter'
            }]
          });
          this.charts.push(chart);
          this.loading.chart4 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化雷达图
        initChart5(data) {
          const chart = echarts.init(this.$refs.chart5);
          chart.setOption({
            title: { text: '雷达图' },
            legend: {
              data: data.legendData || []
            },
            radar: {
              indicator: data.indicators || []
            },
            series: [{
              name: data.seriesName || '数据',
              type: 'radar',
              data: data.seriesData || []
            }]
          });
          this.charts.push(chart);
          this.loading.chart5 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化仪表盘
        initChart6(data) {
          const chart = echarts.init(this.$refs.chart6);
          chart.setOption({
            title: { text: '仪表盘' },
            series: [{
              type: 'gauge',
              progress: {
                show: true,
                width: 18
              },
              axisLine: {
                lineStyle: {
                  width: 18
                }
              },
              detail: {
                valueAnimation: true,
                fontSize: 20,
                offsetCenter: [0, '70%']
              },
              data: [{
                value: data.value || 0,
                name: data.name || '指标'
              }]
            }]
          });
          this.charts.push(chart);
          this.loading.chart6 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化漏斗图
        initChart7(data) {
          const chart = echarts.init(this.$refs.chart7);
          chart.setOption({
            title: { text: '漏斗图' },
            tooltip: {
              trigger: 'item',
              formatter: '{a} <br/>{b} : {c}%'
            },
            legend: {
              data: data.legendData || []
            },
            series: [{
              name: data.seriesName || '漏斗',
              type: 'funnel',
              left: '10%',
              top: 60,
              bottom: 60,
              width: '80%',
              min: 0,
              max: 100,
              minSize: '0%',
              maxSize: '100%',
              sort: 'descending',
              gap: 2,
              label: {
                show: true,
                position: 'inside'
              },
              data: data.seriesData || []
            }]
          });
          this.charts.push(chart);
          this.loading.chart7 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化热力图
        initChart8(data) {
          const chart = echarts.init(this.$refs.chart8);
          chart.setOption({
            title: { text: '热力图' },
            tooltip: {
              position: 'top'
            },
            grid: {
              height: '80%',
              top: '10%'
            },
            xAxis: {
              type: 'category',
              data: data.xAxis || [],
              splitArea: {
                show: true
              }
            },
            yAxis: {
              type: 'category',
              data: data.yAxis || [],
              splitArea: {
                show: true
              }
            },
            visualMap: {
              min: data.minValue || 0,
              max: data.maxValue || 10,
              calculable: true,
              orient: 'horizontal',
              left: 'center',
              bottom: '0%'
            },
            series: [{
              name: data.seriesName || '数据',
              type: 'heatmap',
              data: data.seriesData || [],
              label: {
                show: false
              }
            }]
          });
          this.charts.push(chart);
          this.loading.chart8 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 初始化主题河流图
        initChart9(data) {
          const chart = echarts.init(this.$refs.chart9);
          chart.setOption({
            title: { text: '主题河流图' },
            tooltip: {
              trigger: 'axis',
              axisPointer: {
                type: 'line',
                lineStyle: {
                  color: 'rgba(0,0,0,0.2)',
                  width: 1,
                  type: 'solid'
                }
              }
            },
            legend: {
              data: data.legendData || []
            },
            singleAxis: {
              top: 50,
              bottom: 50,
              axisTick: {},
              axisLabel: {},
              type: 'time',
              axisPointer: {
                animation: true,
                label: {
                  show: true
                }
              },
              splitLine: {
                show: true,
                lineStyle: {
                  type: 'dashed',
                  opacity: 0.2
                }
              }
            },
            series: [{
              type: 'themeRiver',
              emphasis: {
                itemStyle: {
                  shadowBlur: 20,
                  shadowColor: 'rgba(0, 0, 0, 0.8)'
                }
              },
              data: data.seriesData || []
            }]
          });
          this.charts.push(chart);
          this.loading.chart9 = false;
          window.addEventListener('resize', () => chart.resize());
        },

        // 刷新所有图表
        refreshCharts() {
          // 重置加载状态
          Object.keys(this.loading).forEach(key => {
            this.loading[key] = true;
            this.error[key] = null;
          });

          // 销毁现有图表
          this.charts.forEach(chart => chart.dispose());
          this.charts = [];

          // 重新获取数据
          this.fetchAllChartData();
        }
      },
      beforeUnmount() {
        // 清理图表实例和事件监听器
        this.charts.forEach(chart => {
          window.removeEventListener('resize', () => chart.resize());
          chart.dispose();
        });
      }
    };

    const app = Vue.createApp(App);
    app.use(ElementPlus);
    app.mount("#app");
  </script>
</body>
</html>